/*
 * Copyright 2010 Christian Schindelhauer, Peter Thiemann, Faisal Aslam, Luminous Fennell and Gidon Ernst.
 * All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * only, as published by the Free Software Foundation.
 * 
 * This code is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License version 3 for more details (a copy is
 * included in the LICENSE file that accompanied this code).
 * 
 * You should have received a copy of the GNU General Public License
 * version 3 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Faisal Aslam 
 * (aslam AT informatik.uni-freibug.de or studentresearcher AT gmail.com)
 * if you need additional information or have any questions.
 */
package takatuka.vm.autoGenerated.vmSwitch;

import java.io.IOException;
import java.util.*;
import takatuka.classreader.dataObjs.*;
import takatuka.classreader.logic.logAndStats.LogHolder;
import takatuka.classreader.logic.util.Miscellaneous;
import takatuka.tukFormat.dataObjs.LFRevUn;

/**
 * 
 * Description:
 * <p>
 *
 * </p> 
 * @author Faisal Aslam
 * @version 1.0
 */
class OpCodeAndCode {

    public int opCode = -1;
    public String code = "";
    public Vector<String> argumentFunction = new Vector();
    public Vector<String> argumentType = new Vector();
    public String codeWithDefaultAgument = "";
    private static final String OFFSET_FUNCTION = "bytecode_getarg_unsigned_offset";

    OpCodeAndCode() {
    }

    OpCodeAndCode(int opCode, String code, String argumentFunction, String argumentType) {
        this.opCode = opCode;
        this.code = code;
        this.argumentFunction.addElement(argumentFunction);
        this.argumentType.addElement(argumentType);
    }

    public boolean hasArguments() {
        return argumentFunction.size() > 0 ? true : false;
    }

    public String getCodeWithArguments(Vector<Integer> sizesOfIndividualParameters,
            int totalSizeOfParmeters) {
        String ret = code;
        int offSet = totalSizeOfParmeters;
        for (int loop = 0; loop < argumentFunction.size(); loop++) {
            offSet -= sizesOfIndividualParameters.elementAt(loop);
            String funPara = sizesOfIndividualParameters.elementAt(loop) + "";
            if (argumentFunction.elementAt(loop).contains(OFFSET_FUNCTION)) {
                funPara += ", " + offSet;
            }
            String toReplaceWith = argumentType.elementAt(loop)
                    + argumentFunction.elementAt(loop)
                    + "(" + funPara + ")";
            if (loop + 1 < argumentFunction.size()) {
                toReplaceWith += ", ";
            }
            ret = ret.replace("@@" + (loop + 1), toReplaceWith);

        }
        return ret;
    }

    public String getCodeWithArguments(Un fixedArguments, Vector<Integer> sizesOfIndividualParameters) {
        String ret = code;
        try {
            if (argumentFunction.size() != sizesOfIndividualParameters.size()) {
                Miscellaneous.printlnErr("either bytecode defination file is wrong or opcode-parameter file is wrong.");
                Miscellaneous.printlnErr("bytecode defination required " + argumentFunction.size() + " parameters, in "
                        + "contrast the opcode-parameter file required " + sizesOfIndividualParameters.size() + " parameters");
                Miscellaneous.exit();
            }
            
            for (int loop = argumentFunction.size() - 1; loop >= 0; loop--) {
                String nextThingToReplace = "@@" + (loop + 1);
                int argSize = sizesOfIndividualParameters.elementAt(loop);
                Un afterCutting = Un.cutBytes(argSize, fixedArguments);
                String toReplaceWith = "(0x" + afterCutting.toString() + ")";
                if (loop != argumentFunction.size() - 1) {
                    toReplaceWith += ", ";
                }
                ret = ret.replace(nextThingToReplace, argumentType.elementAt(loop)
                        + toReplaceWith);

            }
        } catch (Exception d) {
            Miscellaneous.println("Error in bytecode defination file. " + this
                    + ", " + fixedArguments);
            d.printStackTrace();
            Miscellaneous.exit();
        }
        return ret;
    }

    @Override
    public String toString() {
        return "Opcode=" + opCode + ", code=" + code + ", argument-Type=" + argumentType
                + ", arguments-Function=" + argumentFunction;
    }

    String getCodeWithArguments(int size) throws IOException {
        try {
            return code.replace("@@1", argumentType.elementAt(0)
                    + argumentFunction.elementAt(0) + "(" + size + ")");
        } catch (Exception d) {
            LogHolder.getInstanceOf().addLog("********* Error ********* in function getCodeWithArguments...", true);
            Miscellaneous.println(" Enter a character to continue...");
            System.in.read();
        }
        return "";
    }

    String getCodeWithArguments(Un fixedArg) throws IOException {
        try {
        return code.replace("@@1", argumentType.elementAt(0) + "(0x"
                + fixedArg.toString() + ")");
        } catch(Exception d) {
            LogHolder.getInstanceOf().addLog (" *******ERROR ********* in function getCodeWithArguments...", true);
            Miscellaneous.println(" Enter a character to continue...");
            System.in.read();
        }
        return "";
    }
}
